package com.link510.nbiot.cmcc.impl;

import com.alibaba.fastjson.JSON;
import com.link510.nbiot.cmcc.NBIoTClient;
import com.link510.nbiot.cmcc.exption.NBStatus;
import com.link510.nbiot.cmcc.exption.OnenetNBException;
import com.link510.nbiot.cmcc.helper.HexHelper;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author cqnews
 */
public abstract class AbstractNBIoTClientImpl implements NBIoTClient {


    private static final String HEADER_API_APIKEY = "api-key";


    private final MediaType jsonMediaType = MediaType.parse("application/json; charset=utf-8");

    private final OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(40, TimeUnit.SECONDS)
            .readTimeout(40, TimeUnit.SECONDS)
            .build();


    /**
     * 日志
     */
    private final Logger logger = LoggerFactory.getLogger(AbstractNBIoTClientImpl.class);


    /**
     * Post提交数据
     *
     * @param <T>  类型
     * @param url  url地址
     * @param body 参数
     * @param clzz 类型
     * @return 返回
     * @throws OnenetNBException OnenetNBException
     */
    @Override
    public <T> T restJsonPost(String url, String body, Class<T> clzz) throws OnenetNBException {

        try {

            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(jsonMediaType, body))
                    .header(HEADER_API_APIKEY, getApiKey())
                    .build();

            String s = handleRequest(request);

            return JSON.parseObject(s, clzz);

        } catch (Exception ex) {
            ex.printStackTrace();
            throw new OnenetNBException(NBStatus.HTTP_REQUEST_ERROR, "络加载失败");
        }

    }

    /**
     * Post提交数据
     *
     * @param url  url地址
     * @param body 参数
     * @param clzz 类型
     * @return 返回
     * @throws OnenetNBException OnenetNBException
     */
    @Override
    public <T> T restBinaryPost(String url, String body, Class<T> clzz) throws OnenetNBException {
        try {

            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(jsonMediaType, HexHelper.getInstance().toByteArray(body)))
                    .header(HEADER_API_APIKEY, getApiKey())
                    .build();

            String s = handleRequest(request);

            return JSON.parseObject(s, clzz);

        } catch (Exception ex) {
            ex.printStackTrace();
            throw new OnenetNBException(NBStatus.HTTP_REQUEST_ERROR, "络加载失败");
        }

    }

    /**
     * get请求
     *
     * @param url  url地址
     * @param clzz 类型
     * @param <T>  泛型
     * @return 返回
     * @throws OnenetNBException OnenetNBException
     */
    @Override
    public <T> T restGet(String url, Class<T> clzz) throws OnenetNBException {
        try {

            Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .header(HEADER_API_APIKEY, getApiKey())
                    .build();

            String s = handleRequest(request);

            return JSON.parseObject(s, clzz);

        } catch (Exception ex) {

            throw new OnenetNBException(NBStatus.HTTP_REQUEST_ERROR, "络加载失败");
        }
    }


    /**
     * get请求
     *
     * @param url  url地址
     * @param clzz 类型
     * @param <T>  泛型
     * @return 返回
     * @throws OnenetNBException OnenetNBException
     */
    @Override
    public <T> T restDelete(String url, Class<T> clzz) throws OnenetNBException {
        try {

            Request request = new Request.Builder()
                    .url(url)
                    .delete()
                    .header(HEADER_API_APIKEY, getApiKey())
                    .build();

            String s = handleRequest(request);

            return JSON.parseObject(s, clzz);

        } catch (Exception ex) {

            throw new OnenetNBException(NBStatus.HTTP_REQUEST_ERROR, "络加载失败");
        }
    }

    /**
     * 发起请求
     *
     * @param request 请求
     * @return 返回请求内容
     */
    private String handleRequest(Request request) {
        try {
            Response response = httpClient.newCall(request).execute();

            if (!response.isSuccessful()) {
                throw new OnenetNBException(NBStatus.HTTP_REQUEST_ERROR, "网络异常");
            }

            return new String(response.body() != null ? response.body().bytes() : new byte[0], StandardCharsets.UTF_8);

        } catch (Exception ex) {
            logger.info("http request error::{}", ex.getMessage());
            throw new OnenetNBException(NBStatus.HTTP_REQUEST_ERROR);
        }
    }
}
